/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 combat_object_model_cache.cpp

	$Header: /heroes4/combat_object_model_cache.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "combat_object_model_cache.h"

#include <map>
#include "abstract_resource_cache.h"
#include "compound_object_model.h"

// --------------------------------------------------------------------------
// Unnamed namespace
// --------------------------------------------------------------------------

namespace
{

	struct t_key 
	{
		std::string name;
		double      scale;

		bool operator < (const t_key& arg ) const
		{
			int result = stricmp( name.c_str(), arg.name.c_str() );

			if (result < 0)
				return true;
			if (result > 0)
				return false;
			return scale < arg.scale;
		}
	};

	typedef std::map< t_key, t_combat_object_model_cache > t_cache_map;

	// --------------------------------------------------------------------------
	// t_combat_object_model_cache_data class
	// --------------------------------------------------------------------------

	class t_combat_object_model_cache_data
		:	public t_abstract_resource_cache_data< t_compound_object_model >
	{
	public:
		// Constructor
		t_combat_object_model_cache_data( std::string const & name, double scale_ratio );

	private:
		// Data members
		double	m_scale_ratio;

		// Member functions
		virtual char const *			get_prefix() const;
		virtual t_compound_object_model *	do_read(
											std::streambuf &		stream,
											t_progress_handler *	handler_ptr );
	};


} // Unnamed namespace

// --------------------------------------------------------------------------
// t_combat_object_model_cache members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_combat_object_model_cache::t_combat_object_model_cache(
	std::string const &	name,
	double				scale_ratio )
{
	set( new t_combat_object_model_cache_data( name, scale_ratio ) );
}

// --------------------------------------------------------------------------
// t_combat_object_model_cache_data members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_combat_object_model_cache_data::t_combat_object_model_cache_data(
	std::string const &	name,
	double				scale_ratio )
	:	t_abstract_resource_cache_data< t_compound_object_model >( name ),
		m_scale_ratio( scale_ratio )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
char const * t_combat_object_model_cache_data::get_prefix() const
{
	return t_resource_traits< t_combat_object_model_24 >::prefix;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_compound_object_model * t_combat_object_model_cache_data::do_read(
	std::streambuf &		stream,
	t_progress_handler *	handler_ptr )
{
	t_combat_object_model_24 source;
	if ( !source.read( stream ) )
		return 0;

	return new t_compound_object_model( source, m_scale_ratio );
}


// ------------------------------------------------------------------------------
// get a combat object model given a name and a scale
// ------------------------------------------------------------------------------
t_combat_object_model_cache get_combat_object_model_cache( std::string const& name,
											               double scale_ratio  )
{
	static t_cache_map	  cache_map;
	t_cache_map::iterator result;
	t_key			      key;

	key.name = name;
	key.scale = scale_ratio;
	result = cache_map.find( key );
	if (result != cache_map.end())
	{
		return result->second;
	}

	t_combat_object_model_cache cache( name, scale_ratio );

	cache_map.insert( t_cache_map::value_type(key, cache) );
	return cache;
}

